using System;
using System.Collections.Generic;

using Microsoft.Win32;

using SBPweb.Modules.Modularity;

namespace SBPweb.Contracts.Implementation
{
	/// <summary>
	/// Class of StatePersistenceService
	/// </summary>
	public class StatePersistenceService : IStatePersistenceService
	{
		#region Private members

		/// <summary>
		/// StatePersistenceService
		/// </summary>
		protected static volatile StatePersistenceService pStatePersistenceService = null;
		/// <summary>
		/// Name
		/// </summary>
		protected string pName = "StatePersistenceService";
		/// <summary>
		/// Application registry root
		/// </summary>
		protected string pApplicationRegistryRoot;
		/// <summary>
		/// Application registry key
		/// </summary>
		protected RegistryKey pApplicationRegistryKey = null;

		#endregion

		#region Constructor logic

		/// <summary>
		/// Constructor of StatePersistenceService
		/// </summary>
		/// <param name="companyName">name of the company</param>
		/// <param name="applicationTitle">application title</param>
		private StatePersistenceService(string companyName, string applicationTitle)
		{
			pApplicationRegistryRoot = String.Format(@"Software\{0}\{1}\", companyName, applicationTitle);
			pApplicationRegistryKey = Registry.CurrentUser.CreateSubKey(ApplicationRegistryRoot);
		}

		/// <summary>
		/// Get instance
		/// </summary>
		/// <param name="companyName">name of the company</param>
		/// <param name="applicationTitle">application title</param>
		/// <returns>Persistency service</returns>
		public static StatePersistenceService GetInstance(string companyName, string applicationTitle)
		{
			if (pStatePersistenceService == null)
			{
				pStatePersistenceService = new StatePersistenceService(companyName, applicationTitle);
			}
			return pStatePersistenceService;
		}

		#endregion

		#region Public members

		/// <summary>
		/// Application registry root
		/// </summary>
		public string ApplicationRegistryRoot
		{
			get
			{
				return pApplicationRegistryRoot;
			}
			set
			{
				pApplicationRegistryRoot = value;
			}
		}

		/// <summary>
		/// Application registry key
		/// </summary>
		public RegistryKey ApplicationRegistryKey
		{
			get
			{
				return pApplicationRegistryKey;
			}
			set
			{
				pApplicationRegistryKey = value;
			}
		}

		/// <summary>
		/// Name
		/// </summary>
		public string Name
		{
			get
			{
				return pName;
			}
		}

		#endregion

		#region Private methods

		private RegistryKey OpenKey(IPersistable id)
		{
			if (id != null)
			{
				RegistryKey key = OpenKey(id.ParentPersistable).OpenSubKey(id.PersistencyKey, true);
				if (key == null)
				{
					key = OpenKey(id.ParentPersistable).CreateSubKey(id.PersistencyKey, RegistryKeyPermissionCheck.ReadWriteSubTree);
				}
				return key;
			}
			return pApplicationRegistryKey;
		}

		#endregion

		#region Public methods

		/// <summary>
		/// Is contains id?
		/// </summary>
		/// <param name="id">id</param>
		/// <returns>true or false</returns>
		public bool Contains(SBPweb.Modules.Modularity.IPersistable id)
		{
			RegistryKey key = OpenKey(id.ParentPersistable);
			if (key == null)
			{
				return false;
			}
			List<string> subkeys = new List<string>(key.GetSubKeyNames());
			return subkeys.Contains(id.PersistencyKey);
		}

		/// <summary>
		/// Load
		/// </summary>
		/// <param name="id">id</param>
		/// <returns>persistency</returns>
		public PersistencyDictionary Load(SBPweb.Modules.Modularity.IPersistable id)
		{
			if (Contains(id))
			{
				RegistryKey subKey = OpenKey(id);
				PersistencyDictionary dict = new PersistencyDictionary(id);
				foreach (string subKeyValueName in subKey.GetValueNames())
				{
					dict.SetObject(subKeyValueName, subKey.GetValue(subKeyValueName));
				}
				return dict;
			}
			return new PersistencyDictionary(id);
		}

		/// <summary>
		/// Remove id
		/// </summary>
		/// <param name="id">id</param>
		public void Remove(SBPweb.Modules.Modularity.IPersistable id)
		{
			if (Contains(id))
			{
				RegistryKey key = OpenKey(id.ParentPersistable);
				key.DeleteSubKeyTree(id.PersistencyKey);
			}
		}

		/// <summary>
		/// Save persistency
		/// </summary>
		/// <param name="id">id</param>
		/// <param name="state">current state</param>
		public void Save(SBPweb.Modules.Modularity.IPersistable id, PersistencyDictionary state)
		{
			RegistryKey key = OpenKey(id.ParentPersistable);
			if (!Contains(id))
			{
				key.CreateSubKey(id.PersistencyKey, RegistryKeyPermissionCheck.ReadWriteSubTree);
			}
			RegistryKey subKey = key.OpenSubKey(id.PersistencyKey, true);
			foreach (string subKeyValueName in state.Keys)
			{
				subKey.SetValue(subKeyValueName, state[subKeyValueName]);
			}
		}

		#endregion

		/// <summary>
		/// Module (always returns null, because default services have not got a Host Module)
		/// </summary>
		public IModule Module
		{
			get
			{
				//default services have not got a Host Module
				return null;
			}
		}
	}
}
